package com.ph.clouds.tracker.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author yushuangjiang
 * @Time 2021/8/3 14:35
 * @Description： 线程池
 */
public class TrackThreadPoolManager {

    private static TrackThreadPoolManager singleInstance = new TrackThreadPoolManager();

    public static TrackThreadPoolManager getIntance() {
        return singleInstance;
    }

    //1.将请求任务放到请求队列中
    //通过阻塞式队列来存储任务 FIFO
    private LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

    //添加任务
    public void execute(Runnable runnable) {
        if (runnable != null) {
            try {
                queue.put(runnable);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //2.把队列中的任务放到线程池
    private ThreadPoolExecutor threadPoolExecutor;

    private TrackThreadPoolManager() {
        /**
         * corePoolSize:指定了线程池中的线程数量，它的数量决定了添加的任务是开辟新的线程去执行，还是放到workQueue任务队列中去；
         * maximumPoolSize:指定了线程池中的最大线程数量，这个参数会根据你使用的workQueue任务队列的类型，决定线程池会开辟的最大线程数量；
         * keepAliveTime:当线程池中空闲线程数量超过corePoolSize时，多余的线程会在多长时间内被销毁；
         * unit:keepAliveTime的单位
         * workQueue:任务队列，被添加到线程池中，但尚未被执行的任务；它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种；
         * threadFactory:线程工厂，用于创建线程，一般用默认即可；
         * handler:拒绝策略；当任务太多来不及处理时，如何拒绝任务；
         */
        threadPoolExecutor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(4), rejectedExecutionHandler);
        //运行线程池
        threadPoolExecutor.execute(runnable);

    }

    //当线程数超过maxPoolSize或者keep-alive时间超时时执行拒绝策略
    private RejectedExecutionHandler rejectedExecutionHandler = (runnable, threadPoolExecutor) -> {
        //将该线程重新放入请求队列中
        try {
            queue.put(runnable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    };

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                Runnable runnable = null;
                //从请求队列中取出请求
                try {
                    runnable = queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //如果不为空，放入线程池中执行
                if (runnable != null) {
                    threadPoolExecutor.execute(runnable);
                }
            }

        }
    };

}
